home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWViews / Sources / FWEdView.cpp < prev    next >
Encoding:
Text File  |  1996-08-16  |  26.4 KB  |  909 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWEdView.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWEDVIEW_H
  13. #include "FWEdView.h"
  14. #endif
  15.  
  16. #ifndef FWFRAME_H
  17. #include "FWFrame.h"
  18. #endif
  19.  
  20. #ifndef FWPART_H
  21. #include "FWPart.h"
  22. #endif
  23.  
  24. #ifndef FWDIALOG_H
  25. #include "FWDialog.h"
  26. #endif
  27.  
  28. #ifndef FWEVENT_H
  29. #include "FWEvent.h"
  30. #endif
  31.  
  32. #ifndef FWMNUBAR_H
  33. #include "FWMnuBar.h"
  34. #endif
  35.  
  36. #ifndef FWRECSHP_H
  37. #include "FWRecShp.h"
  38. #endif
  39.  
  40. #ifndef FWSELECT_H
  41. #include "FWSelect.h"
  42. #endif
  43.  
  44. #ifndef FWODGEOM_H
  45. #include "FWODGeom.h"
  46. #endif
  47.  
  48. #ifndef FWWINDOW_H
  49. #include "FWWindow.h"
  50. #endif
  51.  
  52. #ifndef FWCURSOR_H
  53. #include "FWCursor.h"
  54. #endif
  55.  
  56. #ifndef FWFONT_H
  57. #include "FWFont.h"
  58. #endif
  59.  
  60. #ifndef FWEVEDEF_H
  61. #include "FWEveDef.h"
  62. #endif
  63.  
  64. #ifndef FWCONTXT_H
  65. #include "FWContxt.h"
  66. #endif
  67.  
  68. #ifndef FWMEMORY_H
  69. #include "FWMemory.h"
  70. #endif
  71.  
  72. #ifndef SOM_ODFrame_xh
  73. #include <Frame.xh>
  74. #endif
  75.  
  76. #ifndef SOM_ODShape_xh
  77. #include <Shape.xh>
  78. #endif
  79.  
  80. #ifndef SLMIXOS_H
  81. #include <SLMixOS.h>    // for FW_Beep
  82. #endif
  83.  
  84. #ifndef SOM_Module_OpenDoc_Errors_defined
  85. #include <ErrorDef.xh>
  86. #endif
  87.  
  88. #ifdef FW_BUILD_MAC
  89. #include <scrap.h>
  90. #endif
  91.  
  92. //========================================================================================
  93. // Runtime Informations
  94. //========================================================================================
  95.  
  96. #ifdef FW_BUILD_MAC
  97. #pragma segment fwgadgts
  98. #endif
  99.  
  100. FW_DEFINE_CLASS_M2(FW_CEditView, FW_CView, FW_MNotifier)
  101. FW_DEFINE_AUTO(FW_CEditView)
  102.  
  103. //========================================================================================
  104. // Utilities
  105. //========================================================================================
  106.  
  107. inline Rect & operator+= (Rect & r, Point p)
  108. {
  109.     r.top += p.v;
  110.     r.left += p.h;
  111.     r.bottom += p.v;
  112.     r.right += p.h;
  113.     return r;
  114. }
  115.  
  116. #define EDITVIEWCONTEXT(GC,FACET)        \
  117.     FW_CViewContext GC (ev, this, FACET);        \
  118.     MacAdjustRects (ev, GC);                    \
  119.  
  120. #define FW_ISBACKSPACE(c)    (c == 0x08)
  121. #define FW_ISFWDDELETE(c)    (c == 0x7f)
  122. #define FW_ISARROWKEY(c)    (c == 0x1c || c == 0x1d || c == 0x1e || c == 0x1f)
  123. #define FW_ISINPUTCHAR(c)     !FW_ISBACKSPACE(c) && !FW_ISFWDDELETE(c) && !FW_ISARROWKEY(c)
  124.  
  125. //========================================================================================
  126. // CLASS FW_CEditView
  127. //========================================================================================
  128.  
  129. //----------------------------------------------------------------------------------------
  130. // FW_CEditView::FW_CEditView
  131. //----------------------------------------------------------------------------------------
  132.  
  133. FW_CEditView::FW_CEditView (Environment* ev, 
  134.                             FW_CSuperView* container, 
  135.                             ODID viewId, 
  136.                             const FW_CRect& bounds,
  137.                             const FW_CString& str, 
  138.                             const FW_CFont& font,
  139.                             short maxChars, 
  140.                             unsigned short attributes) 
  141.     : FW_CView (ev, container, bounds, viewId),
  142.     fMacTEHandle (nil),
  143.     fMaxChars(maxChars),
  144.     fEditAttributes (attributes)
  145. {
  146.     Initialize(ev, str, font);
  147.     
  148.     FW_END_CONSTRUCTOR
  149. }
  150.  
  151. //----------------------------------------------------------------------------------------
  152. // FW_CEditView::FW_CEditView
  153. //----------------------------------------------------------------------------------------
  154.  
  155. FW_CEditView::FW_CEditView (Environment* ev, 
  156.                             FW_CSuperView* container, 
  157.                             ODID viewId, 
  158.                             const FW_CRect& bounds) 
  159.     : FW_CView (ev, container, bounds, viewId),
  160.     FW_MNotifier(),
  161.     fMacTEHandle (nil),
  162.     fMaxChars(FW_MAXINT16),
  163.     fEditAttributes (FW_CEditView::kDrawBox + FW_CEditView::kAutoScroll)
  164. {
  165.     Initialize(ev, FW_CString(), FW_kNormalFont);
  166.     
  167.     FW_END_CONSTRUCTOR
  168. }
  169.  
  170. //----------------------------------------------------------------------------------------
  171. // FW_CEditView::FW_CEditView
  172. //----------------------------------------------------------------------------------------
  173.  
  174. FW_CEditView::FW_CEditView (Environment* ev) 
  175.     : FW_CView (ev),
  176.     FW_MNotifier(),
  177.     fMacTEHandle (nil),
  178.     fMaxChars(0),
  179.     fEditAttributes(0)
  180. {
  181.     FW_END_CONSTRUCTOR
  182. }
  183.  
  184. //----------------------------------------------------------------------------------------
  185. // FW_CEditView::InitEditView
  186. //----------------------------------------------------------------------------------------
  187.  
  188. void     FW_CEditView::Initialize(Environment* ev, const FW_CString& text, const FW_CFont& font)
  189. {
  190.     // Set up the current port for the TE record  - [LSD] OK to use active facet?
  191.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  192.     FW_ASSERT(facet);
  193.     FW_CPlatformGraphicContext gc (ev, facet);
  194.     
  195.     FW_CPlatformRect pBounds;
  196.     fMacTEHandle = ::TENew (&pBounds, &pBounds);
  197.     if (!fMacTEHandle) 
  198.         FW_Failure (kODErrOutOfMemory);
  199.     
  200.     SetFont(ev, font);    
  201.  
  202.     // Set TE feature flags
  203.     ::TEFeatureFlag(teFAutoScr, (fEditAttributes & FW_CEditView::kAutoScroll) ?
  204.                 teBitSet : teBitClear, fMacTEHandle);
  205.     ::TEFeatureFlag(teFTextBuffering, (fEditAttributes & FW_CEditView::kTextBuffering) ?
  206.                 teBitSet : teBitClear, fMacTEHandle);
  207.     ::TEFeatureFlag(teFOutlineHilite, (fEditAttributes & FW_CEditView::kOutlineHilite) ?
  208.                 teBitSet : teBitClear, fMacTEHandle);
  209.     ::TEFeatureFlag(teFInlineInput, (fEditAttributes & FW_CEditView::kInlineInput) ?
  210.                 teBitSet : teBitClear, fMacTEHandle);
  211.     ::TEFeatureFlag(teFUseTextServices, (fEditAttributes & FW_CEditView::kTextServices) ?
  212.                 teBitSet : teBitClear, fMacTEHandle);
  213.  
  214.     // Mac text-edit is limited to 32K
  215.     if (fMaxChars <= 0 || fMaxChars > FW_MAXINT16)  
  216.         fMaxChars = FW_MAXINT16;
  217.  
  218.     // Access the string buffer directly to pass the char* to TEInsert
  219.     FW_ByteCount bufLen = text.GetByteLength();
  220.     if (bufLen > 0)
  221.     {
  222.         if (bufLen > fMaxChars)
  223.             bufLen = fMaxChars;
  224.             
  225.         const char* buf = text.RevealBuffer();    
  226.         ::TESetText(buf, bufLen, fMacTEHandle);    
  227.     }
  228.     
  229.     // Update TE rects and recompute text layout
  230.     MacSetRects(ev);
  231.     
  232. }
  233.  
  234. //----------------------------------------------------------------------------------------
  235. // FW_CEditView::~FW_CEditView
  236. //----------------------------------------------------------------------------------------
  237.  
  238. FW_CEditView::~FW_CEditView ()
  239. {
  240.     FW_START_DESTRUCTOR
  241.     if (fMacTEHandle)
  242.     {
  243.         // XXX need to test disposing when the window is still up
  244.         ::TEDispose (fMacTEHandle);
  245.     }
  246. }
  247.  
  248. #pragma mark -
  249. //----------------------------------------------------------------------------------------
  250. // FW_CEditView::GetTextLength
  251. //----------------------------------------------------------------------------------------
  252.  
  253. FW_ByteCount FW_CEditView::GetTextLength (Environment * ev) const
  254. {
  255. FW_UNUSED(ev);
  256.  
  257. #if defined(FW_BUILD_MAC)
  258.     return (FW_ByteCount)MacTE()->teLength;    
  259. #endif
  260. }
  261.  
  262. //----------------------------------------------------------------------------------------
  263. // FW_CEditView::GetText
  264. //----------------------------------------------------------------------------------------
  265.  
  266. FW_CString FW_CEditView::GetText (Environment * ev) const
  267. {
  268. FW_UNUSED(ev);
  269.  
  270. #if defined(FW_BUILD_MAC)
  271.     Handle handleText = MacTE()->hText;
  272.     FW_CAcquireLockedSystemHandle locked (handleText);
  273.     return FW_CString(*handleText, (FW_ByteCount)MacTE()->teLength);    
  274. #endif
  275. }
  276.  
  277. //----------------------------------------------------------------------------------------
  278. // FW_CEditView::GetSelectedText
  279. //----------------------------------------------------------------------------------------
  280.  
  281. FW_CString FW_CEditView::GetSelectedText (Environment* ev) const
  282. {
  283. FW_UNUSED(ev);
  284.  
  285. #if defined(FW_BUILD_MAC)
  286.     short startOffset = MacTE()->selStart;
  287.     FW_ByteCount charCount = MacTE()->selEnd - startOffset;
  288.     
  289.     if (charCount <= 0)
  290.         return FW_CString();    // empty selection
  291.  
  292.     Handle handleText = MacTE()->hText;
  293.     FW_CAcquireLockedSystemHandle locked (handleText);
  294.     return FW_CString(*handleText + startOffset, charCount);    
  295. #endif
  296. }
  297.  
  298. //----------------------------------------------------------------------------------------
  299. // FW_CEditView::GetSelectionRange
  300. //----------------------------------------------------------------------------------------
  301.  
  302. void FW_CEditView::GetSelectionRange (Environment* ev, short& startOffset, short& endOffset) const
  303. {
  304. FW_UNUSED(ev);
  305.  
  306. #if defined(FW_BUILD_MAC)
  307.     startOffset = MacTE()->selStart;
  308.     endOffset = MacTE()->selEnd;
  309. #endif
  310. }
  311.  
  312. //----------------------------------------------------------------------------------------
  313. // FW_CEditView::ClearText
  314. //----------------------------------------------------------------------------------------
  315.  
  316. void FW_CEditView::ClearText (Environment* ev)
  317. {
  318.     SetText (ev, FW_CString());
  319. }
  320.  
  321. //----------------------------------------------------------------------------------------
  322. // FW_CEditView::SetText
  323. //----------------------------------------------------------------------------------------
  324.  
  325. void FW_CEditView::SetText (Environment * ev, const FW_CString & str)
  326. {
  327. #if defined(FW_BUILD_MAC)
  328.     // Access the string buffer directly to pass the char* to TEInsert
  329.     FW_ByteCount bufLen = str.GetByteLength();
  330.     if (bufLen > fMaxChars) 
  331.         bufLen = fMaxChars;
  332.     const char* buf = str.RevealBuffer();
  333.  
  334.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  335.     if (facet == NULL) return;        // frame is in limbo
  336.     EDITVIEWCONTEXT (gc, facet);
  337.  
  338.     PrivSelectAll();
  339.     ::TEDelete (fMacTEHandle);
  340.     ::TEInsert (buf, bufLen, fMacTEHandle);    
  341. #endif
  342. }
  343.  
  344. //----------------------------------------------------------------------------------------
  345. // FW_CEditView::SetSelectedText
  346. //----------------------------------------------------------------------------------------
  347.  
  348. void FW_CEditView::SetSelectedText(Environment* ev, const FW_CString& newText)
  349. {
  350. #if defined(FW_BUILD_MAC)
  351.     FW_ByteCount bufLen = newText.GetByteLength();
  352.     const char* buf = newText.RevealBuffer();
  353.  
  354.     // Don't insert more characters than allowed
  355.     FW_ByteCount notSelectedChars = MacTE()->teLength - (MacTE()->selEnd - MacTE()->selStart);
  356.  
  357.     if (notSelectedChars >= fMaxChars) 
  358.         return;
  359.     if ((bufLen + notSelectedChars) > fMaxChars) 
  360.         bufLen = fMaxChars - notSelectedChars;
  361.  
  362.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  363.     if (facet == NULL) return;        // frame is in limbo
  364.     EDITVIEWCONTEXT (gc, facet);
  365.  
  366.     ::TEDelete (fMacTEHandle);                    // delete selected text
  367.     ::TEInsert (buf, bufLen, fMacTEHandle);        // insert new text
  368. #endif
  369. }
  370.  
  371. //----------------------------------------------------------------------------------------
  372. // FW_CEditView::InsertText
  373. //----------------------------------------------------------------------------------------
  374.  
  375. void FW_CEditView::InsertText(Environment* ev, const FW_CString& textToInsert, short offset)
  376. {
  377. #ifdef FW_BUILD_MAC
  378.  
  379.     FW_ByteCount bufLen = textToInsert.GetByteLength();
  380.     const char* buf = textToInsert.RevealBuffer();
  381.  
  382.     // Don't insert more characters than allowed
  383.     FW_ByteCount curLength = MacTE()->teLength;
  384.     if (curLength >= fMaxChars) 
  385.         return;
  386.     if ((bufLen + curLength) > fMaxChars) 
  387.         bufLen = fMaxChars - curLength;
  388.  
  389.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  390.     if (facet == NULL) return;        // frame is in limbo
  391.     EDITVIEWCONTEXT (gc, facet);
  392.  
  393.     ::TESetSelect(offset, offset, fMacTEHandle);
  394.     ::TEInsert(buf, bufLen, fMacTEHandle);
  395. #endif
  396. }
  397.  
  398. //----------------------------------------------------------------------------------------
  399. // FW_CEditView::SelectText
  400. //----------------------------------------------------------------------------------------
  401.  
  402. void FW_CEditView::SelectText(Environment* ev, short startOffset, short endOffset)
  403. {
  404. #ifdef FW_BUILD_MAC
  405.     short offset = startOffset;
  406.     if (startOffset > endOffset)
  407.     {
  408.         startOffset = endOffset;
  409.         endOffset = offset;
  410.     }
  411.         
  412.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  413.     if (facet == NULL) return;        // frame is in limbo
  414.     EDITVIEWCONTEXT (gc, facet);
  415.  
  416.     ::TESetSelect(startOffset, endOffset, fMacTEHandle);
  417. #endif
  418. }
  419.  
  420. //----------------------------------------------------------------------------------------
  421. // FW_CEditView::PrivSelectAll
  422. //----------------------------------------------------------------------------------------
  423. // Used internally when we don't need to create a view context
  424.  
  425. void  FW_CEditView::PrivSelectAll()
  426. {
  427. #ifdef FW_BUILD_MAC
  428.     ::TESetSelect (0, FW_MAXINT16, fMacTEHandle);
  429. #endif
  430. }
  431.  
  432. //----------------------------------------------------------------------------------------
  433. // FW_CEditView::PrivCheckMaxChars
  434. //----------------------------------------------------------------------------------------
  435.  
  436. FW_Boolean  FW_CEditView::PrivCheckMaxChars(long numChars)
  437. {
  438.     // checks if we are trying to add too many chars
  439. #ifdef FW_BUILD_MAC
  440.     long numSelectedChars = MacTE()->selEnd - MacTE()->selStart;
  441.     
  442.     return ((MacTE()->teLength + numChars - numSelectedChars) > fMaxChars);
  443. #endif
  444. }
  445.  
  446. //----------------------------------------------------------------------------------------
  447. // FW_CEditView::SetFont
  448. //----------------------------------------------------------------------------------------
  449.  
  450. void FW_CEditView::SetFont (Environment * ev, const FW_CFont &font)
  451. {
  452. FW_UNUSED(ev);    
  453. #ifdef FW_BUILD_MAC
  454.     MacTE()->txFont = font.MacGetFontID();
  455.     MacTE()->txFace = font.MacGetFontStyle();
  456.     MacTE()->txSize = FW_FixedToInt(font.GetFontSize());
  457. //    MacTE()->txMode = scrOr;
  458.     
  459.     FMInput    fontSpecs;
  460.     fontSpecs.family    = MacTE()->txFont;
  461.     fontSpecs.size        = MacTE()->txSize;
  462.     fontSpecs.face        = MacTE()->txFace;
  463.     fontSpecs.needBits    = false;
  464.     fontSpecs.device    = 0;
  465.     fontSpecs.numer.h    = 1;
  466.     fontSpecs.numer.v    = 1;
  467.     fontSpecs.denom.h    = 1;
  468.     fontSpecs.denom.h    = 1; 
  469.     
  470.     FMOutPtr    fontInfo = ::FMSwapFont(&fontSpecs);    
  471.     MacTE()->lineHeight = fontInfo->ascent + fontInfo->descent + fontInfo->leading;
  472.     MacTE()->fontAscent = fontInfo->ascent;    
  473.     ::TECalText(fMacTEHandle);    
  474.             
  475. #endif
  476. }
  477.  
  478. #pragma mark -
  479. //----------------------------------------------------------------------------------------
  480. // FW_CEditView::SetVisible
  481. //----------------------------------------------------------------------------------------
  482.  
  483. void FW_CEditView::SetVisible(Environment* ev, FW_Boolean visible, FW_Boolean propagate)
  484. {
  485.     FW_CView::SetVisible(ev, visible, propagate);
  486.     
  487.     if (!visible)
  488.     {
  489.         // Will stop idling if this edit view was active
  490.         ResignTarget(ev);    
  491.     }
  492. }
  493.  
  494. //----------------------------------------------------------------------------------------
  495. // FW_CEditView::WantsToBeTarget
  496. //----------------------------------------------------------------------------------------
  497.  
  498. FW_Boolean FW_CEditView::WantsToBeTarget(Environment* ev)
  499. {
  500. FW_UNUSED(ev);
  501.     // Let visible edit views process keys and menu commands
  502.     if (IsVisible(ev))
  503.         return TRUE;
  504.     else
  505.         return FALSE;
  506. }
  507.  
  508. //----------------------------------------------------------------------------------------
  509. // FW_CEditView::ActivateTarget
  510. //----------------------------------------------------------------------------------------
  511.  
  512. void FW_CEditView::ActivateTarget (Environment * ev, FW_Boolean tabSelection)
  513. {
  514.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  515.     FW_ASSERT(facet);
  516.     EDITVIEWCONTEXT (gc, facet);
  517.  
  518.     if (tabSelection)     
  519.         PrivSelectAll();
  520.     else
  521.         AdjustCursor(ev, NULL, FW_kZeroPoint);
  522.     
  523.     ::TEActivate (fMacTEHandle);
  524. }
  525.  
  526. //----------------------------------------------------------------------------------------
  527. // FW_CEditView::DeactivateTarget
  528. //----------------------------------------------------------------------------------------
  529.  
  530. void FW_CEditView::DeactivateTarget (Environment * ev)
  531. {
  532.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  533.     FW_ASSERT(facet);
  534.     EDITVIEWCONTEXT (gc, facet);
  535.     
  536.     ::TEDeactivate (fMacTEHandle);
  537.  
  538.     PrivEnableEditMenu(ev, false);
  539. }
  540.  
  541. //----------------------------------------------------------------------------------------
  542. // FW_CEditView::PrivEnableEditMenu
  543. //----------------------------------------------------------------------------------------
  544.  
  545. void FW_CEditView::PrivEnableEditMenu(Environment *ev, FW_Boolean enable)
  546. {
  547.     // Check if this edit-view belongs to a Modal Dialog before enabling the Edit menu
  548.     FW_CFrame* frame = GetFrame(ev);
  549.     if (GetFrame(ev)->HasModalFocus(ev))
  550.         frame->GetPart(ev)->GetMenuBar(ev)->EnableCommand(ev, kODCommandEditMenu, enable);
  551. }
  552.  
  553. //----------------------------------------------------------------------------------------
  554. // FW_CEditView::DoIdle
  555. //----------------------------------------------------------------------------------------
  556.  
  557. FW_Boolean FW_CEditView::DoIdle (Environment* ev, const FW_CNullEvent& event)
  558. {
  559. FW_UNUSED(event);
  560.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  561.     
  562.     // facet is NULL when frame is in limbo
  563.     if (facet)    
  564.     {
  565.         EDITVIEWCONTEXT (gc, facet);
  566.             
  567. #if defined(FW_BUILD_MAC)
  568.         ::TEIdle (fMacTEHandle);
  569. #endif
  570.     }
  571.     
  572.     return FALSE; 
  573. }
  574.  
  575. //----------------------------------------------------------------------------------------
  576. // FW_CEditView::DoMouseDown
  577. //----------------------------------------------------------------------------------------
  578.  
  579. FW_Boolean FW_CEditView::DoMouseDown (Environment* ev, const FW_CMouseEvent& event)
  580. {
  581.     EDITVIEWCONTEXT (gc, event.GetFacet(ev));
  582.     FW_CPoint where = event.GetMousePosition (ev, FW_CMouseEvent::kFrame);
  583.     FrameToViewContent (ev, where);
  584.     FW_CPlatformPoint pWhere;
  585.     pWhere = gc.LogicalToDevice (where);
  586.     
  587.     ::TEClick (pWhere, event.IsExtendModifier(ev), fMacTEHandle);
  588.     
  589.     return TRUE;
  590. }
  591.  
  592. //----------------------------------------------------------------------------------------
  593. // FW_CEditView::DoVirtualKey
  594. //----------------------------------------------------------------------------------------
  595.  
  596. FW_Boolean FW_CEditView::DoVirtualKey (Environment* ev, const FW_CVirtualKeyEvent & event)
  597. {
  598.     FW_Boolean keyHandled = false;
  599.     short    keyCode = event.GetKeyCode(ev);
  600.         
  601.     if (keyCode == FW_kVKHome || keyCode == FW_kVKEnd) 
  602.     {
  603.         keyHandled = true;
  604.         EDITVIEWCONTEXT (gc, GetFrame(ev)->GetActiveFacet(ev));
  605.         if(keyCode == FW_kVKHome)
  606.             ::TESetSelect(0, 0, fMacTEHandle);                        // Go to the top
  607.         else
  608.             ::TESetSelect(FW_MAXINT16, FW_MAXINT16, fMacTEHandle); // Go to the end
  609.     }
  610.     
  611.     return keyHandled;    // if false key will be handled in DoCharKey
  612. }
  613.  
  614. //----------------------------------------------------------------------------------------
  615. // FW_CEditView::DoCharKey
  616. //----------------------------------------------------------------------------------------
  617.  
  618. FW_Boolean FW_CEditView::DoCharKey (Environment* ev, const FW_CCharKeyEvent & event)
  619. {
  620.     // Ignore Command-characters which are not associated to menu commands
  621.     if (event.GetModifiers() & cmdKey)
  622.         return false;
  623.         
  624.     return InputCharKey(ev, event.GetChar(ev));
  625. }
  626.  
  627. //----------------------------------------------------------------------------------------
  628. // FW_CEditView::InputCharKey
  629. //----------------------------------------------------------------------------------------
  630.  
  631. FW_Boolean FW_CEditView::InputCharKey (Environment* ev, char c)
  632. {
  633.     EDITVIEWCONTEXT (gc, GetFrame(ev)->GetActiveFacet(ev));
  634.     
  635. #if defined(FW_BUILD_MAC)
  636.     if (FW_ISINPUTCHAR(c) && PrivCheckMaxChars(1) == true)
  637.         FW_Beep();
  638.     else
  639.         ::TEKey (c, fMacTEHandle);
  640.         
  641. #endif
  642.     
  643.     return TRUE;
  644. }
  645.  
  646. //----------------------------------------------------------------------------------------
  647. // FW_CEditView::DoAdjustMenus
  648. //----------------------------------------------------------------------------------------
  649.  
  650. FW_Boolean FW_CEditView::DoAdjustMenus (Environment *ev, FW_CMenuBar* menuBar, 
  651.                         FW_Boolean hasMenuFocus, FW_Boolean isRoot)
  652. {
  653. FW_UNUSED(isRoot);
  654.  
  655.     if (hasMenuFocus)
  656.     {
  657.         // Must adjust edit menu for modal dialogs first
  658.         PrivEnableEditMenu(ev, true);
  659.     
  660.         long offset;
  661.         FW_Boolean hasSelection = (MacTE()->selStart != MacTE()->selEnd);
  662.         FW_Boolean hasCharacters = (MacTE()->teLength > 0);
  663.         FW_Boolean hasClipboard = (::GetScrap(0, 'TEXT', &offset) > 0);
  664.  
  665.         menuBar->EnableCommand (ev, kODCommandCut, hasSelection);
  666.         menuBar->EnableCommand (ev, kODCommandCopy, hasSelection);
  667.         menuBar->EnableCommand (ev, kODCommandPaste, hasClipboard);
  668.         menuBar->EnableCommand (ev, kODCommandClear, hasSelection);
  669.         menuBar->EnableCommand (ev, kODCommandSelectAll, hasCharacters);
  670.     }
  671.     return FALSE;    // let parent views adjust their menus
  672. }
  673.  
  674. //----------------------------------------------------------------------------------------
  675. // FW_CEditView::DoTECommand
  676. //----------------------------------------------------------------------------------------
  677.  
  678. void FW_CEditView::DoTECommand (Environment* ev, ODCommandID id, FW_Boolean useScrap)
  679. {
  680.     // DoTECommand can be called by subclasses with useScrap = false when implementing
  681.     // support for ODF Data Interchange (see the Form example) 
  682.  
  683.     ODFacet* facet = GetFrame(ev)->GetActiveFacet(ev);
  684.     FW_ASSERT(facet);
  685.     EDITVIEWCONTEXT (gc, facet);
  686.     
  687.     switch (id) 
  688.     {
  689.         case kODCommandCut:
  690.             ::TECut (fMacTEHandle);
  691.             if (useScrap)
  692.             {
  693.                 ::ZeroScrap();
  694.                 ::TEToScrap();
  695.             }
  696.             break;
  697.  
  698.         case kODCommandCopy: 
  699.             ::TECopy (fMacTEHandle);
  700.             if (useScrap)
  701.             {
  702.                 ::ZeroScrap();
  703.                 ::TEToScrap();
  704.             }
  705.             break;
  706.  
  707.         case kODCommandPaste: 
  708.             if (useScrap)
  709.             {
  710.                 long offset;
  711.                 long scrapLength = ::GetScrap(0, 'TEXT', &offset);
  712.                 if (PrivCheckMaxChars(scrapLength))
  713.                 {
  714.                     FW_Beep();        // can't paste that many characters
  715.                     break;
  716.                 }
  717.                 ::TEFromScrap();
  718.             }
  719.             ::TEPaste (fMacTEHandle);
  720.             break;
  721.  
  722.         case kODCommandClear: 
  723.             ::TEDelete (fMacTEHandle);
  724.             break;
  725.  
  726.         case kODCommandSelectAll: 
  727.             PrivSelectAll();
  728.             break;
  729.     }
  730. }
  731.  
  732. //----------------------------------------------------------------------------------------
  733. // FW_CEditView::DoMenu
  734. //----------------------------------------------------------------------------------------
  735.  
  736. FW_Boolean FW_CEditView::DoMenu (Environment* ev, const FW_CMenuEvent& event)
  737. {
  738.     ODCommandID id = event.GetCommandID(ev);
  739.     
  740.     switch (id) 
  741.     {
  742.         case kODCommandCut: 
  743.         case kODCommandCopy: 
  744.         case kODCommandPaste: 
  745.         case kODCommandClear: 
  746.         case kODCommandSelectAll: 
  747.             DoTECommand(ev, id, true);
  748.             break;
  749.  
  750.         default:
  751.             return FW_CView::DoMenu (ev, event);
  752.     }
  753.     return TRUE;
  754. }
  755.  
  756. //----------------------------------------------------------------------------------------
  757. // FW_CEditView::Draw
  758. //----------------------------------------------------------------------------------------
  759.  
  760. void FW_CEditView::Draw (Environment *ev, ODFacet* facet, ODShape* invalidShape)
  761. {
  762. FW_UNUSED(invalidShape);
  763.     if (HasBox()) {
  764.         // don't use a platform context for the adorners
  765.         FW_CViewContext gc (ev, this, facet); 
  766.         FW_CRect bounds(FW_kZeroPoint, GetSize(ev));
  767.         FW_CRectShape::RenderRect (gc, bounds, FW_kFrame, FW_CInk(FW_kRGBBlack));
  768.         
  769.         // [LSD] Need this? 
  770.         bounds.Inset (FW_kFixedPos1, FW_kFixedPos1);
  771.         FW_CRectShape::RenderRect (gc, bounds, FW_kFill, FW_kWhiteEraseInk);
  772.     }
  773.     EDITVIEWCONTEXT (gc, facet);
  774.     FW_CPlatformRect pBounds = gc.LogicalToDevice (GetTextBounds(ev));
  775.     
  776. #if defined(FW_BUILD_MAC)
  777.     ::TEUpdate (&pBounds, fMacTEHandle);
  778. #endif
  779. }
  780.  
  781. //----------------------------------------------------------------------------------------
  782. // FW_CEditView::AdjustCursor
  783. //----------------------------------------------------------------------------------------
  784.  
  785. FW_Boolean FW_CEditView::AdjustCursor (Environment *ev, ODFacet* odFacet, const FW_CPoint& where)
  786. {
  787. FW_UNUSED(odFacet);
  788. FW_UNUSED(where);
  789.     if (GetFrame(ev)->HasSelectionFocus(ev) == FALSE)            
  790.         return FALSE;
  791.     
  792.     FW_gIBeamCursor.Select();
  793.     return TRUE;
  794. }
  795.  
  796. //----------------------------------------------------------------------------------------
  797. // FW_CEditView::LocationChanged
  798. //----------------------------------------------------------------------------------------
  799.  
  800. void FW_CEditView::LocationChanged (Environment* ev, const FW_CPoint& oldLocation)
  801. {
  802. FW_UNUSED(oldLocation);
  803.     // call MacAdjustRects() instead of MacSetRects() since size didn't change
  804.     EDITVIEWCONTEXT (gc, GetFrame(ev)->GetActiveFacet(ev));
  805. }
  806.  
  807. //----------------------------------------------------------------------------------------
  808. // FW_CEditView::SizeChanged
  809. //----------------------------------------------------------------------------------------
  810.  
  811. void FW_CEditView::SizeChanged (Environment* ev, const FW_CPoint& oldSize)
  812. {
  813. FW_UNUSED(oldSize);
  814.     MacSetRects (ev);
  815. }
  816.  
  817. #pragma mark -
  818. //----------------------------------------------------------------------------------------
  819. // FW_CEditView::GetTextBounds
  820. //----------------------------------------------------------------------------------------
  821.  
  822. FW_CRect FW_CEditView::GetTextBounds (Environment* ev)
  823. {
  824.     // Get view bounds
  825.     FW_CRect bounds (FW_kZeroPoint, GetSize(ev));
  826.     
  827.     // shrink by 2 pixels if the edit view has a box
  828.     if (HasBox())
  829.         bounds.Inset(FW_IntToFixed(2), FW_IntToFixed(2));
  830.  
  831.     return bounds;
  832. }
  833.  
  834. //----------------------------------------------------------------------------------------
  835. // FW_CEditView::MacAdjustRects
  836. //----------------------------------------------------------------------------------------
  837. // MacAdjustRects aligns the TEhandle's rect fields to the view (which may have
  838. // scrolled, etc.).  Don't need to call TECalText here, rect sizes are not
  839. // changed.
  840.  
  841. void FW_CEditView::MacAdjustRects (Environment * ev, FW_CGraphicContext & gc)
  842. {
  843.     FW_CPlatformRect pBounds = gc.LogicalToDevice (GetTextBounds(ev));
  844.     
  845.     if (pBounds != MacTE()->viewRect) {
  846.         FW_CPlatformPoint moving (pBounds.left - MacTE()->viewRect.left, pBounds.top - MacTE()->viewRect.top);
  847.         MacTE()->viewRect += moving;
  848.         MacTE()->destRect += moving;
  849.         MacTE()->selRect += moving;
  850.     }
  851. }
  852.  
  853. //----------------------------------------------------------------------------------------
  854. // FW_CEditView::MacSetRects
  855. //----------------------------------------------------------------------------------------
  856. // MacSetRects resets the TEhandle's rect field at init time or after the view
  857. // has been resized.
  858.  
  859. void FW_CEditView::MacSetRects (Environment * ev)
  860. {
  861.     FW_CViewContext gc (ev, this, GetFrame(ev)->GetActiveFacet(ev));
  862.     FW_CPlatformRect pBounds = gc.LogicalToDevice (GetTextBounds(ev));
  863.     
  864.     MacTE()->viewRect = pBounds;
  865.     MacTE()->destRect = pBounds;    
  866.     
  867.     // extend the destination rectangle far to the right to avoid word wrapping
  868.     // [LSD] this doesn't work with center or right justification
  869.     if (HasWordWrap() == false)
  870.         MacTE()->destRect.right += 2000;
  871.     
  872.     // Let text-edit adjust line breaks
  873.     ::TECalText (fMacTEHandle);
  874. }
  875.  
  876. //----------------------------------------------------------------------------------------
  877. // FW_CEditView::Flatten
  878. //----------------------------------------------------------------------------------------
  879.  
  880. void FW_CEditView::Flatten(Environment* ev, FW_CWritableStream& stream) const
  881. {
  882.     FW_CView::Flatten(ev, stream);
  883.     
  884.     stream << fMaxChars;    
  885.     stream << fEditAttributes;
  886.     stream << FW_CFont(FW_kNormalFont);    // [LSD] reset font to application font
  887.     stream << FW_CString();                // [LSD] reset initial text to empty string
  888. }
  889.  
  890. //----------------------------------------------------------------------------------------
  891. // FW_CEditView::InitializeFromStream
  892. //----------------------------------------------------------------------------------------
  893.  
  894. void FW_CEditView::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
  895. {
  896.     FW_CView::InitializeFromStream(ev, stream);
  897.     
  898.     FW_CString text;
  899.     FW_CFont font;
  900.  
  901.     stream >> fMaxChars;    
  902.     stream >> fEditAttributes;
  903.     stream >> font;
  904.     stream >> text;    
  905.     
  906.     Initialize(ev, text, font);
  907. }
  908.     
  909.